﻿/*******************************************************************************
 * Copyright © Chris Watson 2013                                               *
 *                                                                             *
 * This document is a part of the source code and related artefacts for Chris  *
 * Watson's Desktop Wallpaper Guard, a software application which will detect  *
 * when another process removes the wallpaper from a Windows desktop and       *
 * restore an image of the user's choice.                                      *
 *                                                                             *
 * Author:                                                                     *
 *   Chris Watson       [mailto:chris@watson.me.uk]                            *
 * Date:                                                                       *
 *   17 August 2013                                                            *
 ******************************************************************************/

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Watson.BleaknessEliminator.Properties;

namespace Watson.BleaknessEliminator
{
    /// <summary>
    /// The main form for the Bleakness Eliminator application.
    /// </summary>
    internal partial class MainForm : Form
    {
        #region Private Constants

        

        #endregion

        #region Private Fields

        /// <summary>
        /// An instance of the About Box form. If this field is <c>null</c> no
        /// About Box form is open.
        /// </summary>
        private AboutForm aboutForm = null;


        /// <summary>
        /// The Eliminator.
        /// </summary>
        private Eliminator eliminator = new Eliminator();

        
        /// <summary>
        /// An instance of the Options UI form. If this field is <c>null</c> no
        /// Options UI form is open.
        /// </summary>
        /// <seealso cref="ShowOptions"/>
        private OptionsForm optionsForm = null;

        #endregion

        #region Private Methods

        /// <summary>
        /// Handles the Click event of the btnEnable control.
        /// </summary>
        /// <param name="sender">
        /// The source of the event.
        /// </param>
        /// <param name="e">
        /// The <see cref="EventArgs"/> instance containing the event data.
        /// </param>
        private void btnEnable_Click(object sender, EventArgs e)
        {
            // Enable the Eliminator.
            //
            EnableOrDisableEliminator(true);
        }


        /// <summary>
        /// Handles the Click event of the btnDisable control.
        /// </summary>
        /// <param name="sender">
        /// The source of the event.
        /// </param>
        /// <param name="e">
        /// The <see cref="EventArgs"/> instance containing the event data.
        /// </param>
        private void btnDisable_Click(object sender, EventArgs e)
        {
            // Disable the Eliminator.
            //
            EnableOrDisableEliminator(false);
        }


        /// <summary>
        /// Handles the Click event of the btnOptions control.
        /// </summary>
        /// <param name="sender">
        /// The source of the event.
        /// </param>
        /// <param name="e">
        /// The <see cref="EventArgs"/> instance containing the event data.
        /// </param>
        private void btnOptions_Click(object sender, EventArgs e)
        {
            // Show the options UI.
            //
            ShowOptions();
        }


        /// <summary>
        /// Enables or disables the Eliminator.
        /// </summary>
        /// <param name="value">
        /// Enables the Eliminator if set to <c>true</c>; else, disables the
        /// Eliminator.
        /// </param>
        private void EnableOrDisableEliminator(bool value)
        {
            // Enable or disable the Eliminator.
            //
            eliminator.Enabled = value;

            // Refresh the UI to reflect new enabled state.
            ShowAvailableActions();
        }


        /// <summary>
        /// Initialises the displayed form items.
        /// </summary>
        private void InitialiseDisplay()
        {
            // Set form caption.
            //
            Text = Util.AssemblyInfo.Default.DisplayName;
        }
        

        /// <summary>
        /// Initialises the application's notification area icon.
        /// </summary>
        private void InitialiseNotifyIcon()
        {
            // Set the icon for the notification area icon.
            //
            notifyIconEliminator.Icon = Resources.Icon;

            // Set the ToolTip text for the notification area icon.
            //
            notifyIconEliminator.Text = Util.AssemblyInfo.Default.DisplayName;
        }


        /// <summary>
        /// Handles the MouseDoubleClick event of the notifyIconEliminator
        /// control.
        /// </summary>
        /// <param name="sender">
        /// The source of the event.
        /// </param>
        /// <param name="e">
        /// The <see cref="MouseEventArgs"/> instance containing the event data.
        /// </param>
        private void notifyIconEliminator_MouseDoubleClick(object sender,
            MouseEventArgs e)
        {
            // Show the options UI.
            //
            ShowOptions();
        }


        /// <summary>
        /// Shows the about box window to the user.
        /// </summary>
        private void ShowAboutBox()
        {
            // If we don't currently have an about box form, initialise one.
            //
            if (aboutForm == null || aboutForm.IsDisposed)
            {
                aboutForm = new AboutForm();

                aboutForm.FormClosed += (sender, e) =>
                {
                    aboutForm.Dispose();

                    aboutForm = null;
                };

            }

            // Show the about box form.
            //
            aboutForm.Show();

            // In case we have an existing minimised about box form, restore it.
            //
            if (aboutForm.WindowState == FormWindowState.Minimized)
            {
                aboutForm.WindowState = FormWindowState.Normal;
            }

            // Bring the about box form to the front of the z-order.
            //
            aboutForm.BringToFront();
        }


        /// <summary>
        /// Shows the available actions.
        /// </summary>
        private void ShowAvailableActions()
        {
            if (eliminator.Enabled)
            {
                btnEnable.Enabled                = false;
                btnDisable.Enabled               = true;

                toolStripMenuItemEnable.Visible  = false;
                toolStripMenuItemDisable.Visible = true;
            }
            else
            {
                btnEnable.Enabled                = true;
                btnDisable.Enabled               = false;

                toolStripMenuItemEnable.Visible  = true;
                toolStripMenuItemDisable.Visible = false;
            }
        }


        /// <summary>
        /// Shows the options user interface to the user.
        /// </summary>
        private void ShowOptions()
        {
            // If we don't currently have a options form, initialise one.
            //
            if (optionsForm == null || optionsForm.IsDisposed)
            {
                optionsForm = new OptionsForm();

                optionsForm.FormClosed += (sender, e) =>
                {
                    optionsForm.Dispose();

                    optionsForm = null;
                };
            
            }

            // Show the options form.
            //
            optionsForm.Show();

            // In case we have an existing minimised options form, restore it.
            //
            if (optionsForm.WindowState == FormWindowState.Minimized)
            {
                optionsForm.WindowState = FormWindowState.Normal;
            }

            // Bring the options form to the front of the z-order.
            //
            optionsForm.BringToFront();
        }


        /// <summary>
        /// Handles the Click event of the toolStripMenuItemAbout control.
        /// </summary>
        /// <param name="sender">
        /// The source of the event.
        /// </param>
        /// <param name="e">
        /// The <see cref="EventArgs"/> instance containing the event data.
        /// </param>
        private void toolStripMenuItemAbout_Click(object sender, EventArgs e)
        {
            // Show the About Box.
            //
            ShowAboutBox();
        }


        /// <summary>
        /// Handles the Click event of the toolStripMenuItemDisable control.
        /// </summary>
        /// <param name="sender">
        /// The source of the event.
        /// </param>
        /// <param name="e">
        /// The <see cref="EventArgs"/> instance containing the event data.
        /// </param>
        private void toolStripMenuItemDisable_Click(object sender, EventArgs e)
        {
            // Disable the Eliminator.
            //
            EnableOrDisableEliminator(false);
        }


        /// <summary>
        /// Handles the Click event of the toolStripMenuItemEnable control.
        /// </summary>
        /// <param name="sender">
        /// The source of the event.
        /// </param>
        /// <param name="e">
        /// The <see cref="EventArgs"/> instance containing the event data.
        /// </param>
        private void toolStripMenuItemEnable_Click(object sender, EventArgs e)
        {
            // Enable the Eliminator.
            //
            EnableOrDisableEliminator(true);
        }


        /// <summary>
        /// Handles the Click event of the toolStripMenuItemExit control.
        /// </summary>
        /// <param name="sender">
        /// The source of the event.
        /// </param>
        /// <param name="e">
        /// The <see cref="EventArgs"/> instance containing the event data.
        /// </param>
        private void toolStripMenuItemExit_Click(object sender, EventArgs e)
        {
            // Exit the application.
            //
            Application.Exit();
        }


        /// <summary>
        /// Handles the Click event of the toolStripMenuItemOptions control.
        /// </summary>
        /// <param name="sender">
        /// The source of the event.
        /// </param>
        /// <param name="e">
        /// The <see cref="EventArgs"/> instance containing the event data.
        /// </param>
        private void toolStripMenuItemOptions_Click(object sender, EventArgs e)
        {
            // Show the options UI.
            //
            ShowOptions();
        }
        
        #endregion

        #region Protected Methods

        /// <summary>
        /// Sets the form to the specified visible state.
        /// </summary>
        /// <param name="value">
        /// <c>true</c> to make the control visible; otherwise, <c>false</c>.
        /// </param>
        protected override void SetVisibleCore(bool value)
        {
            if (!this.IsHandleCreated)
            {
                value = false;
                CreateHandle();
            }

            base.SetVisibleCore(value);
        }

        
        /// <summary>
        /// Processes a Windows message.
        /// </summary>
        /// <param name="m">
        /// The Windows <see cref="T:System.Windows.Forms.Message" /> to
        /// process.
        /// </param>
        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);
            
            /*
             * Process Windows messages for the desktop change notification.
             * Ref: http://www.neowin.net/forum/topic/567779-net-detect-wallpape
             *      r-change/
             */
            
            // If the message is WM_SETTINGCHANGE and the WParam field is
            // SPI_SETDESKWALLPAPER...
            //
            if (m.Msg == NativeMethods.WM_SETTINGCHANGE &&
                m.WParam.ToInt32() == NativeMethods.SPI_SETDESKWALLPAPER)
            {
                // ...then the wallpaper has changed. Notify the Eliminator.
                //
                eliminator.NotifyWallpaperChanged();
            }
        }

        #endregion

        #region Internal Constructors

        /// <summary>
        /// Initialises a new instance of the <see cref="MainForm"/> class.
        /// </summary>
        internal MainForm()
        {
            // Set Form Designer properties.
            //
            InitializeComponent();

            // Initialise form items.
            //
            InitialiseDisplay();

            // Initialise notification area icon.
            //
            InitialiseNotifyIcon();

            // Show actions available to the user.
            //
            ShowAvailableActions();
        }

        #endregion
    }
}
